#include "replaceOutliers.h"
#include "CubicSpline.h" // 包含 CubicSpline 类
#include <algorithm>
#include <numeric>
#include <cmath>

// 构造函数
replaceOutliers::replaceOutliers(const QVector<double>& t, const QVector<double>& y, const QVector<bool>& outliers)
    : t(t), y(y), outliers(outliers), method("remove"), opt1(-1), opt2(-1) {}

// 设置替换方法
void replaceOutliers::setMethod(const QString& method, int opt1, int opt2) {
    this->method = method;
    this->opt1 = opt1;
    this->opt2 = opt2;
}

// 执行替换
QPair<QVector<double>, QVector<double>> replaceOutliers::execute() {
    QVector<double> t2 = t;
    QVector<double> y2 = y;

    if (method == "remove") {
        removeOutliers(t2, y2);
    } else if (method == "mean") {
        meanReplacement(y2);
    } else if (method == "median") {
        medianReplacement(y2);
    } else if (method == "spline" || method == "cubic") {
        splineReplacement(y2);
    }

    return qMakePair(t2, y2);
}

// 删除异常值
void replaceOutliers::removeOutliers(QVector<double>& t2, QVector<double>& y2) {
    for (int i = y.size()  - 1; i >= 0; --i) {
        if (outliers[i]) {
            t2.remove(i);
            y2.remove(i);
        }
    }
}

// 均值替换
// 设置替换方法为均值替换，窗口大小为 3（即左右各取 1 个点）
void replaceOutliers::meanReplacement(QVector<double>& y2) {
    int m = std::floor((opt1 - 1) / 2);
    for (int i = 0; i < y.size();  ++i) {
        if (outliers[i] && i >= m && i < y.size()  - m) {
            QVector<double> window;
            for (int j = i - m; j <= i + m; ++j) {
                if (!outliers[j]) {
                    window.append(y[j]);
                }
            }
            if (!window.isEmpty())  {
                double mean = std::accumulate(window.begin(),  window.end(),  0.0) / window.size();
                y2[i] = mean;
            }
        }
    }
}

// 中值替换
// 设置替换方法为中值替换，窗口大小为 3（即左右各取 1 个点）
void replaceOutliers::medianReplacement(QVector<double>& y2) {
    int m = std::floor((opt1 - 1) / 2);
    for (int i = 0; i < y.size();  ++i) {
        if (outliers[i] && i >= m && i < y.size()  - m) {
            QVector<double> window;
            for (int j = i - m; j <= i + m; ++j) {
                if (!outliers[j]) {
                    window.append(y[j]);
                }
            }
            if (!window.isEmpty())  {
                std::sort(window.begin(),  window.end());
                double median = window[window.size() / 2];
                y2[i] = median;
            }
        }
    }
}

// 样条插值替换
// 设置替换方法为样条插值
void replaceOutliers::splineReplacement(QVector<double>& y2) {
    QVector<double> t_temp, y_temp;
    for (int i = 0; i < y.size();  ++i) {
        if (!outliers[i]) {
            t_temp.append(t[i]);
            y_temp.append(y[i]);
        }
    }
    CubicSpline spline(t_temp, y_temp);
    for (int i = 0; i < y.size();  ++i) {
        if (outliers[i]) {
            y2[i] = spline.interpolate(t[i]);
        }
    }
}
